#include "command_process.h"
#include "cn_crc.h"
#include <string.h>
#include "stdlib.h"
#include "cn_tcpserver.h"
/*****************************************************************************
协议说明:
	wifi端使用自定义协议进行收发
	帧头(0x7E) + 长度(两个字节) + 通信comm(一字节) + 类型Type(一字节) + 指令cmd(一字节) +留空(4字节) + 数据区data + CRC(两字节) + 帧尾(0xE7)
	
	长度:从通信到数据区的长度，不包括起始域、长度域、校验域、结束域
	
	CRC：从通信开始到数据域结束的CRC16校验值（注意不需要计算起始域、长度和结束域）
	
	通信comm：
	0x01:代表UDP通信
	0x02:代表TCP Client通信
	0x03:代表TCP Server通信
	0x04:代表串口

	类型Type:
	0x01:代表是配置类型
	0x02:代表是透传类型，也就是数据转发给串口

	指令cmd:
	如类型Type为0x01，则代表的就是配置指令
	如类型Type为0x02，则代表的意义如下：
	0x01：代表是串口1数据
	0x02: 代表是串口2数据
	0x03: 代表是串口3数据
	0x04: 代表是串口4数据	
	0xFF:代表所有串口
	0x05~0xFF：待补充
*****************************************************************************/
const uint8_t HeadCMD = 0x7E;
const uint8_t RearCMD = 0xE7;
/******************************************************************************
Function   : uint32_t cmd_get(uint8_t *cmdBuf, struct fifo_data *fifo)
Description: get command frame from fifo
Input      : cmdBuf - getted command frame storage state
             fifo - fifo handle 
Output     : uint32_t - the fifo position
Author     : RCSN
Time       : 2018-6-14
******************************************************************************/
uint32_t cmd_get(uint8_t *cmdBuf, struct fifo_data *fifo)
{
	uint16_t i;	
	ERRR(fifo == NULL, goto ERR1);    
	ERRR(fifo_empty(fifo) == TRUE, goto ERR1);        //FIFO为空，返回0
	i = fifo_find(fifo, &HeadCMD, sizeof(HeadCMD));  //寻找帧头
	fifo->front = i; //把寻找到的帧头赋值给fifo的头
	ERRR(fifo_validSize(fifo) < 3, goto ERR1);      //FIFO为空，返回0
	//当遇到一帧数据的长度域的第一个字节在fifo的的最后一个字节的时候
	if((fifo->size - 1) == ((fifo->front + sizeof(HeadCMD))%fifo->size)) 
	{
		i  = (uint16_t)fifo->data[fifo->size - 1]; //得到长度
		i += (uint16_t)(fifo->data[0] << 8);
	}
	else
	{
	//		i = *(uint16_t *)&fifo->data[(fifo->front + sizeof(HeadCMD))%fifo->size]; //得到长度
		memcpy(&i,&fifo->data[(fifo->front + sizeof(HeadCMD))%fifo->size],2);
	}
	ERRR(i > CMD_SIZE, goto ERR5);      //length数据不对，超过了1024

	ERRR(fifo_validSize(fifo) < (i + 6), goto ERR1);      //如果剩余长度小于有效数据长度	
	if((fifo->size - fifo->front + 1) < (i + 6))
	{
		//根据得到的长度往fifo的存储数据偏移到指定长度后的值是否为尾帧，是的话就继续，否则识为错误帧，将头移除
		ERRR(fifo->data[i + 5 - (fifo->size-fifo->front)] != RearCMD,goto ERR2); //指令长度不对
	}
	else
	{
		//根据得到的长度往fifo的存储数据偏移到指定长度后的值是否为尾帧，是的话就继续，否则识为错误帧，将头移除
		ERRR(fifo->data[((fifo->front + i + 5)%fifo->size)] != RearCMD,goto ERR3); //指令长度不对
	}


	ERRR(i == 0, goto ERR1);  //数据指令长度错误
	ERRR(i > CMD_SIZE, goto ERR4);  //数据指令长度错误
	ERRR(i > fifo_validSize(fifo), goto ERR1); //数据空间不够	
	ERRR(fifo_gets(fifo, cmdBuf, (i + 6)) == FALSE, goto ERR1);   //数据内容出队,补上起始域和长度域结束帧等6个字节
	ERRR((ChkCrcValueEx(&cmdBuf[3],(i + 2),0xFFFF) != 0), goto ERR6);    //CRC检验错误	
	// wm_printf("cmd_get:");
    // for (u32 j = 0; j< (i + 6);j++)
    // {
    //     wm_printf("%02x ",cmdBuf[j]);
    // }
    // wm_printf("\r\n");
	return (i + 3); //返回的不包括CRC和结束域3个字节
ERR1:   return 0;
ERR2:   fifo->front = (fifo->front+sizeof(HeadCMD))%fifo->size;printf("error2"); return 0; //数据错误将头移出
ERR3:   fifo->front = (fifo->front+sizeof(HeadCMD))%fifo->size;printf("error3"); return 0;//数据错误将头移出
ERR4:   fifo->front = (fifo->front+sizeof(HeadCMD))%fifo->size;printf("error4"); return 0;//数据错误将头移出
ERR5:   fifo->front = (fifo->front+sizeof(HeadCMD))%fifo->size;printf("error5"); return 0;//数据错误将头移出	
ERR6:   fifo->front = (fifo->size + fifo->front - (i + 6) + sizeof(HeadCMD))%fifo->size;printf("error6");  return 0;//数据错误将头移出
	
}

/******************************************************************************
Function   : uint32_t cmd_put(struct fifo_data *fifo, uint8_t *cmdBuf, uint32_t cmdLen)
Description: put a command frame to send fifo
Input      : fifo - handle fifo
             cmdBuf - to be treated data
             cmdLen - data length
Output     : 0 - FALSE, 1 - TURE
Author     : RCSN
Time       : 2018-6-20
******************************************************************************/
uint32_t cmd_put(struct fifo_data *fifo, uint8_t *cmdBuf, uint32_t cmdLen) //此时的cmdlen是一帧的全部长度
{
	uint16_t crc = 0;
   ERRR(fifo == NULL, goto ERR1);
	ERRR(cmdLen > CMD_SIZE, goto ERR1);
	crc = ChkCrcValueEx(cmdBuf + 3,cmdLen - 6,0xFFFF); //这里是计算不包括起始域，长度域，CRC，结束域6个字节的CRC，故需要减去6
	*(uint16_t*)(cmdBuf + cmdLen - 3) = crc;
	*(cmdBuf+cmdLen - 1) = RearCMD;	
	// wm_printf("cmd_put:");
    // for (u32 i = 0; i < cmdLen; i++)
    // {
    //     wm_printf("%02x ",cmdBuf[i]);
    // }
    // wm_printf("\r\n");
  ERRR(fifo_puts(fifo, cmdBuf, cmdLen) == FALSE, goto ERR1); 
  return TRUE;
ERR1:   return FALSE;
}

//把收到的数据压包到对应的FIFO
void recv_msg_package(uint8_t type,uint8_t *data,uint32_t lenth)
{
	struct comdata comdata_t;
	comdata_t.start = HeadCMD;
	comdata_t.length = lenth + 1;//1是固定字节，也就是类型
	comdata_t.type = type;
	memcpy(comdata_t.data,data,lenth);
// 	cmd_put(&rcv_wlan_fifo, (uint8_t *)&comdata_t, (comdata_t.length + 6));
}

//把串口收到的数据压包到对应的FIFO
void recv_usart_package(uint8_t type,uint8_t *data,uint32_t lenth)
{
	struct comdata comdata_t;
	printf("recv_usart_package:%d type:%d\r\n",lenth,type);
	comdata_t.start = HeadCMD;
	comdata_t.length = lenth + 7;//1是固定字节，也就是类型
	comdata_t.comm = 2;
	comdata_t.type = 2;
	comdata_t.cmd  = type;
	comdata_t.segno = 1;
	comdata_t.segtl = 1;
	memcpy(comdata_t.data,data,lenth);
	cmd_put(&rcv_usart_fifo, (uint8_t *)&comdata_t, (comdata_t.length + 6));	
}
